/**
 * *********************** ******* ***********************************
 *
 *  
 * 
 *  
 * *******************************************************************
 */

package com.arges.web.common;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import java.util.Vector;

import org.apache.commons.lang3.StringUtils;

/**
 * 日期操作通用方法类
 *
 * 
 * @version Ver 3.0
 * @since Ver 3.0
 * @Date 2012-9-8
 *
 */
public class DateUtil
{

	/** yyyy-MM-dd */
	public static String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";

	/** HH:mm:ss */
	public static String DEFAULT_TIME_FORMAT = "HH:mm:ss";

	/** yyyy-MM */
	public static String DEFAULT_YEAR_MONTH = "yyyy-MM";

	/** MM-dd */
	public static String DEFAULT_MONTH_DAY = "MM-dd";

	/** yyyy-MM-dd HH:mm:ss */
	public static String DEFAULT_DATE_TIME = "yyyy-MM-dd HH:mm:ss";

	/** yyyy/MM/dd */
	public static String DEFAULT_DATE_TIME_PATH = "yyyy/MM/dd";

	/** yyyy/MM */
	public static String YEAR_MONTH_PATH = "yyyy/MM";

	/** yyyy-MM-dd EEEE HH:mm:ss */
	public static String DEFAULT_DATE_WEEK_TIME = "yyyy-MM-dd EEEE HH:mm:ss";

	/** yyyy-MM-dd EEEE */
	public static String DEFAULT_DATE_WEEK = "yyyy-MM-dd EEEE";

	/** yyyy-MM-dd HH:mm:ss */
	public static String DEFAULT_DATE_NOSECONDS = "yyyy-MM-dd HH:mm:ss";

	public static String TIME_MIN = "00:00:00";

	public static String TIME_MAX = "23:59:59";

	/** oracle date time */
	public static String DEFAULT_DATE_ORACLE = "yyyy-MM-dd hh24:mi:ss";

	public static String convertDate2String(String dateFormat)
	{
		return convertDate2String(new Date(), dateFormat);
	}

	/**
	 * 将日期转换成指定格式的字符串
	 * 
	 * @param date - 要转换的日期
	 * @param dateFormat - 日期格式
	 * @return String 日期对应的字符串
	 */
	public static String convertDate2String(Date date, String dateFormat)
	{
		SimpleDateFormat sdf;
		if (dateFormat != null && !dateFormat.equals(""))
		{
			try
			{
				sdf = new SimpleDateFormat(dateFormat);
			}
			catch (Exception e)
			{
				sdf = new SimpleDateFormat(DEFAULT_DATE_FORMAT + " " + DEFAULT_TIME_FORMAT);
			}
		}
		else
		{
			sdf = new SimpleDateFormat(DEFAULT_DATE_FORMAT + " " + DEFAULT_TIME_FORMAT);
		}
		return sdf.format(date);
	}

	/**
	 * 毫秒数转换为日志
	 * 
	 * @param date - 要转换的日期
	 * @param dateFormat - 日期格式
	 * @return String 日期对应的字符串
	 * @throws ParseException
	 */
	public static Date convertLong2Date(Long time) throws ParseException
	{
		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(time);
		return calendar.getTime();
	}

	/**
	 * 将日期转换成指定格式的字符串
	 * 
	 * @param date - 要转换的日期
	 * @param dateFormat - 日期格式
	 * @return String 日期对应的字符串
	 */
	public static String convertDate2String(Date date, String dateFormat, Locale locale)
	{
		SimpleDateFormat sdf;
		if (dateFormat != null && !dateFormat.equals(""))
		{
			try
			{
				sdf = new SimpleDateFormat(dateFormat, locale);
			}
			catch (Exception e)
			{
				sdf = new SimpleDateFormat(DEFAULT_DATE_FORMAT + " " + DEFAULT_TIME_FORMAT, locale);
			}
		}
		else
		{
			sdf = new SimpleDateFormat(DEFAULT_DATE_FORMAT + " " + DEFAULT_TIME_FORMAT, locale);
		}
		return sdf.format(date);
	}

	/**
	 * 将时间字符串转换为时间
	 * 
	 * @param sdate 需要转换的字符串
	 * @param dateFormat 转换格式
	 * @return 转换后的时间
	 * @throws ParseException
	 * @since Ver 3.0
	 */
	public static Date convertString2Date(String sdate, String dateFormat)
	{
		SimpleDateFormat sdf;
		if (dateFormat != null && !dateFormat.equals(""))
		{
			try
			{
				sdf = new SimpleDateFormat(dateFormat);
			}
			catch (Exception e)
			{
				sdf = new SimpleDateFormat(DEFAULT_DATE_FORMAT + " " + DateUtil.DEFAULT_TIME_FORMAT);
			}
		}
		else
		{
			sdf = new SimpleDateFormat(DEFAULT_DATE_FORMAT + " " + DateUtil.DEFAULT_TIME_FORMAT);
		}
		try
		{
			return sdf.parse(sdate);
		}
		catch (ParseException e)
		{
			return null;
		}
	}

	/**
	 * 将时间字符串转换为时间
	 * 
	 * @param sdate 需要转换的字符串
	 * @param dateFormat 转换格式
	 * @return 转换后的时间
	 * @throws ParseException
	 * @since Ver 3.0
	 */
	public static Date convertString2Date(String sdate, String dateFormat, Locale locale) throws ParseException
	{
		if (StringUtils.isNotBlank(sdate))
		{
			SimpleDateFormat sdf;
			if (dateFormat != null && !dateFormat.equals(""))
			{
				try
				{
					sdf = new SimpleDateFormat(dateFormat, locale);
				}
				catch (Exception e)
				{
					sdf = new SimpleDateFormat(DEFAULT_DATE_FORMAT + " " + DateUtil.DEFAULT_TIME_FORMAT, locale);
				}
			}
			else
			{
				sdf = new SimpleDateFormat(DEFAULT_DATE_FORMAT + " " + DateUtil.DEFAULT_TIME_FORMAT, locale);
			}
			return sdf.parse(sdate);
		}
		else
		{
			return null;
		}
	}

	/**
	 * 取得当前日期所在周的第一天
	 *
	 * @param date
	 * @return
	 */
	public static Date getFirstDayOfWeek(Date date)
	{
		Calendar c = new GregorianCalendar();
		c.setFirstDayOfWeek(Calendar.MONDAY);
		c.setTime(date);
		c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek()); // Monday
		return c.getTime();
	}

	/**
	 * 取得当前日期所在周的最后一天
	 *
	 * @param date
	 * @return
	 */
	public static Date getLastDayOfWeek(Date date)
	{
		Calendar c = new GregorianCalendar();
		c.setFirstDayOfWeek(Calendar.MONDAY);
		c.setTime(date);
		c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek() + 6); // Sunday
		return c.getTime();
	}

	public static int getDayNumsOfMonth(String date)
	{
		SimpleDateFormat sdp = new SimpleDateFormat(DateUtil.DEFAULT_YEAR_MONTH);
		Date D_date = new Date();
		try
		{
			D_date = sdp.parse(date);
		}
		catch (Exception e)
		{
		}
		Calendar cal = new GregorianCalendar();
		cal.setTime(D_date);
		return cal.getActualMaximum(Calendar.DAY_OF_MONTH);
	}

	public static GregorianCalendar[] getBetweenDate(String d1, String d2) throws ParseException
	{
		Vector<GregorianCalendar> v = new Vector<GregorianCalendar>();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		GregorianCalendar gc1 = new GregorianCalendar(), gc2 = new GregorianCalendar();
		gc1.setTime(sdf.parse(d1));
		gc2.setTime(sdf.parse(d2));
		do
		{
			GregorianCalendar gc3 = (GregorianCalendar) gc1.clone();
			v.add(gc3);
			gc1.add(Calendar.DAY_OF_MONTH, 1);
		}
		while (!gc1.after(gc2));
		return v.toArray(new GregorianCalendar[v.size()]);
	}

	public static String AllDateOfMonth(String date)
	{
		StringBuilder sb = new StringBuilder();
		SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.DEFAULT_MONTH_DAY);
		sb.append("[");
		try
		{
			GregorianCalendar[] ga = getBetweenDate(date + "-01", date + "-" + getDayNumsOfMonth(date));
			for (int i = 0; i < ga.length - 1; i++)
			{
				sb.append("\"" + sdf.format(ga[i].getTime()) + "\"");
				sb.append(",");
			}
			sb.append("\"" + sdf.format(ga[ga.length - 1].getTime()) + "\"");
		}
		catch (Exception e)
		{
		}
		sb.append("]");
		return sb.toString();
	}

	public static String AllSimpleDateOfMonth(String date)
	{
		StringBuilder sb = new StringBuilder();
		sb.append("[");
		int nums = getDayNumsOfMonth(date);
		for (int i = 1; i < nums; i++)
		{
			sb.append("\"" + i + "\"");
			sb.append(",");
		}
		sb.append("\"" + nums + "\"");
		sb.append("]");
		return sb.toString();
	}

	public static int getDayOfWeek(Date date)
	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int num = cal.get(Calendar.DAY_OF_WEEK);
		return num - 1;
	}

	public static int getDayOfDate(Date date)
	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(Calendar.DAY_OF_MONTH);
	}

	public static int getMonthOfDate(Date date)
	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(Calendar.MONTH);
	}

	/**
	 * 生成指定天数后的日期
	 * 
	 * @param days 指定天数
	 * @return 数字形式的日期
	 */
	public static int createByDays(int days)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DATE, days);
		SimpleDateFormat dateFormat = new SimpleDateFormat(DateUtil.DEFAULT_DATE_TIME);
		return Integer.parseInt(dateFormat.format(calendar.getTime()));
	}

	/**
	 * 根据传入日期生成指定天数后的日期
	 * 
	 * @param date 传入日期
	 * @param days 指定天数
	 * @return 日期
	 */
	public static Date createByDays(Date date, int days)
	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DATE, days);
		return (Date) cal.getTime();
	}

	/**
	 * 根据传入的日期和时间，生成日期
	 * 
	 * @param date 传入日期
	 * @param time 时间，格式 HH:mm:ss 或 HH:mm
	 * @return 日期
	 */
	public static Date createDay(Date date, String time)
	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		if (time.length() == 5)
		{
			time += ":00";
		}
		String[] intTime = time.split(":");
		cal.set(Calendar.HOUR_OF_DAY, Integer.valueOf(intTime[0]));
		cal.set(Calendar.MINUTE, Integer.valueOf(intTime[1]));
		cal.set(Calendar.SECOND, Integer.valueOf(intTime[2]));
		return (Date) cal.getTime();
	}

	/**
	 * 返回date1与date2相差的分钟数
	 * 
	 * @param date1
	 * @param date2
	 * @return int
	 */
	public static int MinDiff(Date date1, Date date2)
	{
		int i = (int) ((date1.getTime() - date2.getTime()) / 1000 / 60);
		return i;
	}

	/**
	 * 将Date转换为int形 格式(yyyyMMdd)
	 * 
	 * @param date 日期对象
	 * @return 日期的整数形式
	 */
	public static int toInteger(Date date)
	{
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.YEAR) * 10000 + (c.get(Calendar.MONTH) + 1) * 100 + c.get(Calendar.DAY_OF_MONTH);
	}

	/**
	 * 按yyyyMMdd格式比较两个日期的大小
	 * 
	 * @param date1 比较的第一个日期
	 * @param date2 比较的第二个日期
	 * @return 两个日期相等返回0,date1大于date2返回1,date1小于date2返回-1.
	 */
	public static int compareTo(Date date1, Date date2)
	{
		int intDate1 = toInteger(date1);
		int intDate2 = toInteger(date2);
		return intDate1 >= intDate2 ? (intDate1 == intDate2 ? 0 : 1) : -1;
	}

	/**
	 * 按yyyyMMdd G:i:s格式比较两个日期的大小
	 * 
	 * @param date1 比较的第一个日期
	 * @param date2 比较的第二个日期
	 * @return 两个日期相等返回0,date1大于date2返回1,date1小于date2返回-1.
	 */
	public static int compareTime(Date date1, Date date2)
	{
		long intDate1 = date1.getTime();
		long intDate2 = date2.getTime();
		return intDate1 >= intDate2 ? (intDate1 == intDate2 ? 0 : 1) : -1;
	}

	/**
	 * 返回两个日期相差年数
	 * 
	 * @param start
	 * @param end
	 * @return int
	 */
	public static int yearsOf(Date start, Date end)
	{
		Calendar c1 = Calendar.getInstance();
		c1.setTime(start);
		Calendar c2 = Calendar.getInstance();
		c2.setTime(end);
		return c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR) + 1;
	}

	/**
	 * 计算两日之间的间隔天数
	 * 
	 * @param startday 开始日期
	 * @param endday 结束日期
	 * @return 间隔天数
	 */
	public static int getDays(Date startday, Date endday)
	{
		Calendar startCal = Calendar.getInstance();
		Calendar endCal = Calendar.getInstance();
		startCal.setTime(startday);
		endCal.setTime(endday);
		return (int) ((endCal.getTime().getTime() - startCal.getTime().getTime()) / (1000 * 60 * 60 * 24));
	}

	/**
	 * 计算两日之间的间隔天数,忽略时间，只比较日期
	 * 
	 * @param startday 开始日期
	 * @param endday 结束日期
	 * @return 间隔天数
	 */
	public static int getDaysIgnoreTime(Date startday, Date endday)
	{
		Calendar startCal = Calendar.getInstance();
		Calendar endCal = Calendar.getInstance();
		startCal.setTime(startday);
		startCal.set(Calendar.HOUR_OF_DAY, 0);
		startCal.set(Calendar.MINUTE, 0);
		startCal.set(Calendar.SECOND, 0);
		startCal.set(Calendar.MILLISECOND, 0);

		endCal.setTime(endday);
		endCal.set(Calendar.HOUR_OF_DAY, 0);
		endCal.set(Calendar.MINUTE, 0);
		endCal.set(Calendar.SECOND, 0);
		endCal.set(Calendar.MILLISECOND, 0);
		return (int) ((endCal.getTime().getTime() - startCal.getTime().getTime()) / (1000 * 60 * 60 * 24));
	}

	/**
	 * 将数字格式的时间,转换为字符串表示,如120000 -> 12:00:00
	 * 
	 * @param time 数字格式的时间
	 * @return 字符串格式的时间
	 */
	public static String formatTime(int time)
	{
		int hour = time / 10000;
		int min = (time - hour * 10000) / 100;
		int sec = time - hour * 10000 - min * 100;
		String hours = hour + "";
		String mins = min + "";
		String secs = sec + "";
		if (0 <= hour && hour <= 9)
			hours = "0" + hour;
		if (0 <= min && min <= 9)
			mins = "0" + min;
		if (0 <= sec && sec <= 9)
			secs = "0" + sec;
		return hours + ":" + mins + ":" + secs;
	}

	/**
	 * 
	 * 比较两个时间区间是否有重叠的部分 (必须保证参数的开始时间要小于结束时间)
	 * 
	 * @param dateBegin1 区间段1的开始时间
	 * @param dateEnd1 区间段1的结束时间
	 * @param dateBegin2 区间段2的开始时间
	 * @param dateEnd2 区间段2的结束时间
	 * @return 是否有重叠，true：重叠，false：不重叠
	 * @since Ver 3.0
	 */
	public static boolean isTimeOverlapping(Date dateBegin1, Date dateEnd1, Date dateBegin2, Date dateEnd2)
	{
		if (!(compareTime(dateEnd1, dateBegin2) < 0 || compareTime(dateBegin1, dateEnd2) > 0))
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	/**
	 * 
	 * 获得两个区间断点的重叠段
	 *
	 * @param dateBegin1
	 * @param dateEnd1
	 * @param dateBegin2
	 * @param dateEnd2
	 * @return
	 * @since Ver 3.0
	 */
	public static List<Date> getTheOverlappingPart(Date dateBegin1, Date dateEnd1, Date dateBegin2, Date dateEnd2)
	{
		List<Date> Overlapping = new ArrayList<Date>();
		if (!isTimeOverlapping(dateBegin1, dateEnd1, dateBegin2, dateEnd2))
		{
			return null;
		}
		else
		{
			if (compareTime(dateBegin1, dateBegin2) >= 0)
			{
				Overlapping.add(dateBegin1);
			}
			else
			{
				Overlapping.add(dateBegin2);
			}
			if (compareTime(dateEnd1, dateEnd2) <= 0)
			{
				Overlapping.add(dateEnd1);
			}
			else
			{
				Overlapping.add(dateEnd2);
			}
			return Overlapping;
		}
	}

	/**
	 * 
	 * 根据日期和给出的需重复星期，得到真实的开始日期
	 *
	 * @param date 开始日期
	 * @param weeks 重复的星期
	 * @return
	 * @since Ver 3.0
	 */
	public static Date getRealDateByWeeks(Date date, List<Integer> weeks)
	{
		int week = getDayOfWeek(date);
		int day = 0;// 间隔天数
		Collections.sort(weeks);
		if (weeks.contains(week))
		{
			return date;
		}
		else
		{
			if (week > Collections.max(weeks))
			{
				day = calculateDayFromTwoWeek(week, Collections.min(weeks));
			}
			else if (week < Collections.min(weeks))
			{
				day = calculateDayFromTwoWeek(week, Collections.min(weeks));
			}
			else
			{
				int position = Collections.binarySearch(weeks, week);
				day = calculateDayFromTwoWeek(week, weeks.get(-position - 1));
			}
			return createByDays(date, day);
		}
	}

	/**
	 * 
	 * 计算两个星期几的间隔天数,在连续的两个星期内计算 间隔的星期数不计算在内
	 *
	 * @param start 开始星期
	 * @param end 结束星期
	 * @return
	 * @since Ver 3.0
	 */
	public static int calculateDayFromTwoWeek(int start, int end)
	{
		int week = 0;
		if (start < end)
		{
			week = end - start;
		}
		else if (start > end)
		{
			week = 7 - start + end;
		}
		return week;
	}

	/**
	 * 
	 * 设置日期的时分秒
	 *
	 * @param hour 时
	 * @param minute 分
	 * @param second 秒
	 * @return
	 * @since Ver 3.0
	 */
	public static Date setTimeOfDate(Date date, int hour, int minute, int second)
	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.HOUR_OF_DAY, hour);
		cal.set(Calendar.MINUTE, minute);
		cal.set(Calendar.SECOND, second);
		return cal.getTime();
	}

	/**
	 * 获取当前时间
	 * 
	 * @param timeType
	 * @return
	 */
	public static String getNowTime(String timeType)
	{
		java.util.Date now = new java.util.Date();
		if (timeType == null)
		{
			timeType = DEFAULT_DATE_TIME;
		}
		SimpleDateFormat simpleDateTimeFormat = new SimpleDateFormat(timeType);
		return simpleDateTimeFormat.format(now);
	}

	/**
	 * 
	 * createByMonths:(生成指定月数后的日期)
	 *
	 * @param months
	 * @return
	 * @throws
	 * @since Ver 1.1
	 */
	public static Date createByMonthsLater(int months)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.MONTH, months);
		return calendar.getTime();
	}

	/**
	 * 
	 * getDateFunction:(获取数据库的时间函数Mysql和Oracle不同)
	 * 
	 * @param date
	 * @param dateFormat
	 * @return
	 * @throws
	 * @since Ver 3.0
	 */
	public static String getDateFunction(String date, String dateFormat)
	{
		String result = "";
		if (dateFormat == null || ("").equals(dateFormat))
		{
			dateFormat = DEFAULT_DATE_ORACLE;
		}
		if (DEFAULT_DATE_ORACLE.equals(dateFormat))
		{
			result = "str_to_date('" + date + "','%Y-%m-%d %H:%i:%s')";
		}
		else if (DEFAULT_DATE_FORMAT.equals(dateFormat))
		{
			result = "str_to_date('" + date + "','%Y-%m-%d')";
		}
		return result;
	}

	/**
	 * 
	 * getToCharFunction:(获取数据库的时间函数Mysql和Oracle不同)
	 *
	 * @param date
	 * @param dateFormat
	 * @return
	 * @throws
	 * @since Ver 1.1
	 */
	public String getToCharFunction(String date, String dateFormat)
	{
		String result = "";
		if (dateFormat == null || ("").equals(dateFormat))
		{
			dateFormat = DEFAULT_DATE_ORACLE;
		}
		if (DEFAULT_DATE_ORACLE.equals(dateFormat))
		{
			result = "date_format(" + date + ",'%Y-%m-%d %H:%i:%s')";
		}
		else if (DEFAULT_DATE_FORMAT.equals(dateFormat))
		{
			result = "date_format(" + date + ",'%Y-%m-%d')";
		}
		else if ("hh24:mi:ss".equals(dateFormat))
		{
			result = "date_format(" + date + ",'%H:%i:%s')";
		}
		return result;
	}
}
